package config

import (
	xlog "Hypnos-Soundcore/components/log"
	"Hypnos-Soundcore/constants"
	"github.com/gin-gonic/gin"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"path/filepath"
	"strings"
	"sync"
)

var once sync.Once
var conf *XConfig
var stopChan chan bool

// GetXConfig .
func GetXConfig() *XConfig {
	once.Do(func() {
		conf = defaultConfg()
	})
	return conf
}

// 默认配置信息
func defaultConfg() *XConfig {
	return &XConfig{
		Gin:     GinConfig{Mode: gin.DebugMode, RSARequest: false, AesEncrypt: false},
		Swagger: SwaggerConfig{false, "", ""},
		Network: NetworkConfig{ListenPort: ":8080"},
		Log:     LogConfig{false, xlog.LevelName(xlog.LevelDebug), "sample.log"},
	}
}

// LoadConfig load config from file
func (xconf *XConfig) LoadConfig(path string) (err error) {
	if !filepath.IsAbs(path) {
		file, fileErr := filepath.Abs(path)
		if fileErr != nil {
			err = fileErr
			return
		}
		path = file
	}

	bts, ioErr := ioutil.ReadFile(path)
	if ioErr != nil {
		err = ioErr
		return
	}

	err = yaml.Unmarshal(bts, xconf)
	// err = ffjson.Unmarshal(bts, xconf)

	if err == nil {
		err = xconf.verify()
	}
	return
}

// LoadConfig load config from file
func LoadConfig(path string) (xconf *XConfig, err error) {
	xconf = GetXConfig()
	err = xconf.LoadConfig(path)
	return
}

// IsAesEncrypt 请求是否加密
func IsAesEncrypt() bool {
	return GetXConfig().Gin.AesEncrypt
}

// IsLogUserOp 是否保存用户操作记录
func IsLogUserOp() bool {
	return GetXConfig().Gin.LogUserOp
}

func logWatchMessage(subid, msg string) {
	xlog.WarningActionPrintln(constants.TagConfig, constants.ActionServiceConfigWatch, subid, msg, 0)
}

// ReleaseConfigWatch 释放配置更新监听
func ReleaseConfigWatch() {
	if stopChan != nil {
		close(stopChan)
	}
}

// AutoAlarmEnabled 只有QA和US环境需要支持自动报警
func AutoAlarmEnabled(userID string) (ret bool) {
	xc := GetXConfig()
	if !xc.AutoAlarm.Enabled {
		// 禁用自动报警
		return
	}
	// 允许自动报警
	if len(xc.AutoAlarm.WhiteList) == 0 {
		// 若未设置白名单则默认全部用户允许自动报警
		ret = true
		return
	}
	// 若设置白名单则白名单中的用户才允许自动报警
	for _, uid := range xc.AutoAlarm.WhiteList {
		if uid == userID {
			ret = true
			break
		}
	}
	return
}

func logMessage(actid, subid, msg string) {
	xlog.WarningActionPrintln(constants.TagConfig, actid, subid, msg, 0)
}

// BindDeviceNeedCheckCode 绑定设备是否需要检查check_code
func BindDeviceNeedCheckCode(sn, version string) (ret bool) {
	xc := GetXConfig()
	ret = xc.BindDeviceCheckCode.DefaultNeedCheckCode
	if len(sn) == 0 {
		return
	}
	if len(xc.BindDeviceCheckCode.MinStationVersions) == 0 {
		return
	}
	minVer, ok := xc.BindDeviceCheckCode.MinStationVersions[sn]
	if !ok {
		return
	}
	if strings.Compare(version, minVer) >= 0 {
		// 若当前基站版本大于等于配置的最小版本则需要检查check_code
		ret = true
	}
	return
}
